home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / misc / gs261src.zip / iutilasm.asm < prev    next >
Assembly Source File  |  1993-05-13  |  9KB  |  459 lines

  1. ;    Copyright (C) 1989, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2. ;
  3. ; This file is part of Ghostscript.
  4. ;
  5. ; Ghostscript is distributed in the hope that it will be useful, but
  6. ; WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. ; to anyone for the consequences of using it or for whether it serves any
  8. ; particular purpose or works at all, unless he says so in writing.  Refer
  9. ; to the Ghostscript General Public License for full details.
  10. ;
  11. ; Everyone is granted permission to copy, modify and redistribute
  12. ; Ghostscript, but only under the conditions described in the Ghostscript
  13. ; General Public License.  A copy of this license is supposed to have been
  14. ; given to you along with Ghostscript so you can know your rights and
  15. ; responsibilities.  It should be in a file named COPYING.  Among other
  16. ; things, the copyright notice and this notice must be preserved on all
  17. ; copies.
  18.  
  19. ; iutilasm.asm
  20. ; Assembly code for Ghostscript interpreter on MS-DOS systems
  21.  
  22.     ifdef    FOR80386
  23.  
  24.     .286c
  25.  
  26.     endif
  27.  
  28. utilasm_TEXT    SEGMENT    WORD PUBLIC 'CODE'
  29.     ASSUME    CS:utilasm_TEXT
  30.  
  31.  
  32.     ifdef    FOR80386
  33.  
  34. ; Macro for 32-bit operand prefix.
  35. OP32    macro
  36.     db    66h
  37.     endm
  38.  
  39.     endif                    ; FOR80386
  40.  
  41.  
  42.     ifdef    FOR80386
  43.  
  44. ; Replace the multiply and divide routines in the Turbo C library
  45. ; if we are running on an 80386.
  46.  
  47. ; Macro to swap the halves of a 32-bit register.
  48. ; Unfortunately, masm won't allow a shift instruction with a count of 16,
  49. ; so we have to code it in hex.
  50. swap    macro    regno
  51.       OP32
  52.     db    0c1h,0c0h+regno,16        ; rol regno,16
  53.     endm
  54. regax    equ    0
  55. regcx    equ    1
  56. regdx    equ    2
  57. regbx    equ    3
  58.  
  59. ; Multiply (dx,ax) by (cx,bx) to (dx,ax).
  60.     PUBLIC    LXMUL@
  61.     PUBLIC    F_LXMUL@
  62. F_LXMUL@ proc    far
  63. LXMUL@    proc    far
  64.     swap    regdx
  65.     mov    dx,ax
  66.     swap    regcx
  67.     mov    cx,bx
  68.       OP32
  69.     db    0fh,0afh,0d1h            ; imul dx,cx
  70.       OP32
  71.     mov    ax,dx
  72.     swap    regdx
  73.     ret
  74. LXMUL@    endp
  75. F_LXMUL@ endp
  76.  
  77. ; Divide two stack operands, leave the result in (dx,ax).
  78.  
  79.     ifdef    DEBUG
  80.  
  81. setup32    macro
  82.     mov    bx,sp
  83.     push    bp
  84.     mov    bp,sp
  85.       OP32
  86.     mov    ax,ss:[bx+4]            ; dividend
  87.     endm
  88.  
  89. ret32    macro    n
  90.     mov    sp,bp
  91.     pop    bp
  92.     ret    n
  93.     endm
  94.  
  95.     else                    ; !DEBUG
  96.  
  97. setup32    macro
  98.     mov    bx,sp
  99.       OP32
  100.     mov    ax,ss:[bx+4]            ; dividend
  101.     endm
  102.  
  103. ret32    macro    n
  104.     ret    n
  105.     endm
  106.  
  107.     endif                    ; (!)DEBUG
  108.  
  109.     PUBLIC    LDIV@, LUDIV@, LMOD@, LUMOD@
  110.     PUBLIC    F_LDIV@, F_LUDIV@, F_LMOD@, F_LUMOD@
  111. F_LDIV@    proc    far
  112. LDIV@    proc    far
  113.     setup32
  114.       OP32
  115.     cwd
  116.       OP32
  117.     idiv    word ptr ss:[bx+8]        ; divisor
  118.       OP32
  119.     mov    dx,ax
  120.     swap    regdx
  121.     ret32    8
  122. LDIV@    endp
  123. F_LDIV@    endp
  124. F_LUDIV@ proc    far
  125. LUDIV@    proc    far
  126.     setup32
  127.       OP32
  128.     xor    dx,dx
  129.       OP32
  130.     div    word ptr ss:[bx+8]        ; divisor
  131.       OP32
  132.     mov    dx,ax
  133.     swap    regdx
  134.     ret32    8
  135. LUDIV@    endp
  136. F_LUDIV@ endp
  137. F_LMOD@    proc    far
  138. LMOD@    proc    far
  139.     setup32
  140.       OP32
  141.     cwd
  142.       OP32
  143.     idiv    word ptr ss:[bx+8]        ; divisor
  144.       OP32
  145.     mov    ax,dx
  146.     swap    regdx
  147.     ret32    8
  148. LMOD@    endp
  149. F_LMOD@    endp
  150. F_LUMOD@ proc    far
  151. LUMOD@    proc    far
  152.     setup32
  153.       OP32
  154.     xor    dx,dx
  155.       OP32
  156.     div    word ptr ss:[bx+8]        ; divisor
  157.       OP32
  158.     mov    ax,dx
  159.     swap    regdx
  160.     ret32    8
  161. LUMOD@    endp
  162. F_LUMOD@ endp
  163.  
  164.     else                    ; !FOR80386
  165.  
  166. ; Replace the divide routines in the Turbo C library,
  167. ; which do the division one bit at a time (!).
  168.  
  169.     PUBLIC    LDIV@, LMOD@, LUDIV@, LUMOD@
  170.     PUBLIC    F_LDIV@, F_LMOD@, F_LUDIV@, F_LUMOD@
  171.  
  172. ; Negate a long on the stack.
  173. negbp    macro    offset
  174.     neg    word ptr [bp+offset+2]        ; high part
  175.     neg    word ptr [bp+offset]        ; low part
  176.     sbb    word ptr [bp+offset+2],0
  177.     endm
  178.  
  179. ; Negate a long in (dx,ax).
  180. negr    macro
  181.     neg    dx
  182.     neg    ax
  183.     sbb    dx,0
  184.     endm
  185.  
  186. ; Divide two unsigned longs on the stack.
  187. ; Leave either the quotient or the remainder in (dx,ax).
  188. ; Operand offsets assume that bp (and only bp) has been pushed.
  189. nlo    equ    6
  190. nhi    equ    8
  191. dlo    equ    10
  192. dhi    equ    12
  193.  
  194. ; We use an offset in bx to distinguish div from mod,
  195. ; and to indicate whether the result should be negated.
  196. odiv    equ    0
  197. omod    equ    2
  198. odivneg    equ    4
  199. omodneg    equ    6
  200. F_LMOD@    proc    far
  201. LMOD@    proc    far
  202.     push    bp
  203.     mov    bp,sp
  204.     mov    bx,omod
  205.             ; Take abs of denominator
  206.     cmp    byte ptr [bp+dhi+1],bh        ; bh = 0
  207.     jge    modpd
  208.     negbp    dlo
  209. modpd:            ; Negate mod if numerator < 0
  210.     cmp    byte ptr [bp+nhi+1],bh        ; bh = 0
  211.     jge    udiv
  212.     mov    bx,omodneg
  213. negnum:    negbp    nlo
  214.     jmp    udiv
  215. LMOD@    endp
  216. F_LMOD@    endp
  217. F_LUMOD@ proc    far
  218. LUMOD@    proc    far
  219.     mov    bx,omod
  220.     jmp    udpush
  221. LUMOD@    endp
  222. F_LUMOD@ endp
  223. F_LDIV@    proc    far
  224. LDIV@    proc    far
  225.     push    bp
  226.     mov    bp,sp
  227.     mov    bx,odiv
  228.             ; Negate quo if num^den < 0
  229.     mov    ax,[bp+nhi]
  230.     xor    ax,[bp+dhi]
  231.     jge    divabs
  232.     mov    bx,odivneg
  233. divabs:            ; Take abs of denominator
  234.     cmp    byte ptr [bp+dhi+1],bh        ; bh = 0
  235.     jge    divpd
  236.     negbp    dlo
  237. divpd:            ; Take abs of numerator
  238.     cmp    byte ptr [bp+nhi+1],bh        ; bh = 0
  239.     jge    udiv
  240.     jmp    negnum
  241. LDIV@    endp
  242. F_LDIV@    endp
  243. F_LUDIV@ proc    far
  244. LUDIV@    proc    far
  245.     mov    bx,odiv
  246. udpush:    push    bp
  247.     mov    bp,sp
  248. udiv:    push    bx                ; odiv, omod, odivneg, omodneg
  249.     mov    ax,[bp+nlo]
  250.     mov    dx,[bp+nhi]
  251.     mov    bx,[bp+dlo]
  252.     mov    cx,[bp+dhi]
  253. ; Now we are dividing dx:ax by cx:bx.
  254. ; Check to see whether this is really a 32/16 division.
  255.     or    cx,cx
  256.     jnz    div2
  257. ; 32/16, check for 16- vs. 32-bit quotient
  258.     cmp    dx,bx
  259.     jae    div1
  260. ; 32/16 with 16-bit quotient, just do it.
  261.     div    bx                ; ax = quo, dx = rem
  262.     pop    bx
  263.     pop    bp
  264.     jmp    cs:xx1[bx]
  265.     even
  266. xx1    dw    offset divx1
  267.     dw    offset modx1
  268.     dw    offset divx1neg
  269.     dw    offset modx1neg
  270. modx1:    mov    ax,dx
  271. divx1:    xor    dx,dx
  272.     ret    8
  273. modx1neg: mov    ax,dx
  274. divx1neg: xor    dx,dx
  275. rneg:    negr
  276.     ret    8
  277. ; 32/16 with 32-bit quotient, do in 2 parts.
  278. div1:    mov    cx,ax                ; save lo num
  279.     mov    ax,dx
  280.     xor    dx,dx
  281.     div    bx                ; ax = hi quo
  282.     xchg    cx,ax                ; save hi quo, get lo num
  283.     div    bx                ; ax = lo quo, dx = rem
  284.     pop    bx
  285.     pop    bp
  286.     jmp    cs:xx1a[bx]
  287.     even
  288. xx1a    dw    offset divx1a
  289.     dw    offset modx1
  290.     dw    offset divx1aneg
  291.     dw    offset modx1neg
  292. divx1a:    mov    dx,cx                ; hi quo
  293.     ret    8
  294. divx1aneg: mov    dx,cx
  295.     jmp    rneg
  296. ; This is really a 32/32 bit division.
  297. ; (Note that the quotient cannot exceed 16 bits.)
  298. ; The following algorithm is taken from pp. 235-240 of Knuth, vol. 2
  299. ; (first edition).
  300. ; Start by normalizing the numerator and denominator.
  301. div2:    or    ch,ch
  302.     jz    div21                ; ch == 0, but cl != 0
  303. ; Do 8 steps all at once.
  304.     mov    bl,bh
  305.     mov    bh,cl
  306.     mov    cl,ch
  307.     xor    ch,ch
  308.     mov    al,ah
  309.     mov    ah,dl
  310.     mov    dl,dh
  311.     xor    dh,dh
  312.     rol    bx,1                ; faster than jmp
  313. div2a:    rcr    bx,1                ; finish previous shift
  314. div21:    shr    dx,1
  315.     rcr    ax,1
  316.     shr    cx,1
  317.     jnz    div2a
  318.     rcr    bx,1
  319. ; Now we can do a 32/16 divide.
  320. div2x:    div    bx                ; ax = quo, dx = rem
  321. ; Multiply by the denominator, and correct the result.
  322.     mov    cx,ax                ; save quotient
  323.     mul    word ptr [bp+dhi]
  324.     mov    bx,ax                ; save lo part of hi product
  325.     mov    ax,cx
  326.     mul    word ptr [bp+dlo]
  327.     add    dx,bx
  328. ; Now cx = trial quotient, (dx,ax) = cx * denominator.
  329.     not    dx
  330.     neg    ax
  331.     cmc
  332.     adc    dx,0                ; double-precision neg
  333.     jc    divz                ; zero quotient
  334.                         ; requires special handling
  335.     add    ax,[bp+nlo]
  336.     adc    dx,[bp+nhi]
  337.     jc    divx
  338. ; Quotient is too large, adjust it.
  339. div3:    dec    cx
  340.     add    ax,[bp+dlo]
  341.     adc    dx,[bp+dhi]
  342.     jnc    div3
  343. ; All done.  (dx,ax) = remainder, cx = lo quotient.
  344. divx:    pop    bx
  345.     pop    bp
  346.     jmp    cs:xx3[bx]
  347.     even
  348. xx3    dw    offset divx3
  349.     dw    offset modx3
  350.     dw    offset divx3neg
  351.     dw    offset modx3neg
  352. divx3:    mov    ax,cx
  353.     xor    dx,dx
  354. modx3:    ret    8
  355. divx3neg: mov    ax,cx
  356.     xor    dx,dx
  357. modx3neg: jmp    rneg
  358. ; Handle zero quotient specially.
  359. divz:    pop    bx
  360.     jmp    cs:xxz[bx]
  361.     even
  362. xxz    dw    offset divxz
  363.     dw    offset modxz
  364.     dw    offset divxz
  365.     dw    offset modxzneg
  366. divxz:    pop    bp
  367.     ret    8
  368. modxzneg: negbp    nlo
  369. modxz:    mov    ax,[bp+nlo]
  370.     mov    dx,[bp+nhi]
  371.     pop    bp
  372.     ret    8
  373. LUDIV@    endp
  374. F_LUDIV@ endp
  375.  
  376.     endif                    ; FOR80386
  377.  
  378. ; Transpose an 8x8 bit matrix.  See gsmisc.c for the algorithm in C.
  379.     PUBLIC    _memflip8x8
  380. _memflip8x8 proc far
  381.     push    ds
  382.     push    si
  383.     push    di
  384.         ; After pushing, the offsets of the parameters are:
  385.         ; byte *inp=10, int line_size=14, byte *outp=16, int dist=20.
  386.     mov    si,sp
  387.     mov    di,ss:[si+14]            ; line_size
  388.     lds    si,ss:[si+10]            ; inp
  389.         ; We assign variables to registers as follows:
  390.         ; ax = AE, bx = BF, cx (or di) = CG, dx = DH.
  391.         ; Load the input data.  Initially we assign
  392.         ; ax = AB, bx = EF, cx (or di) = CD, dx = GH.
  393.     mov    ah,[si]
  394. iload    macro    reg
  395.     add    si,di
  396.     mov    reg,[si]
  397.     endm
  398.     iload    al
  399.     iload    ch
  400.     iload    cl
  401.     iload    bh
  402.     iload    bl
  403.     iload    dh
  404.     iload    dl
  405.         ; Transposition macro, see C code for explanation.
  406. trans    macro    reg1,reg2,shift,mask
  407.     mov    si,reg1
  408.     shr    si,shift
  409.     xor    si,reg2
  410.     and    si,mask
  411.     xor    reg2,si
  412.     shl    si,shift
  413.     xor    reg1,si
  414.     endm
  415.         ; Do 4x4 transpositions
  416.     mov    di,cx            ; we need cl for the shift count
  417.     mov    cl,4
  418.     trans    bx,ax,cl,0f0fh
  419.     trans    dx,di,cl,0f0fh
  420.         ; Swap B/E, D/G
  421.     xchg    al,bh
  422.     mov    cx,di
  423.     xchg    cl,dh
  424.         ; Do 2x2 transpositions
  425.     mov    di,cx                ; need cl again
  426.     mov    cl,2
  427.     trans    di,ax,cl,3333h
  428.     trans    dx,bx,cl,3333h
  429.     mov    cx,di                ; done shifting >1
  430.         ; Do 1x1 transpositions
  431.     trans    bx,ax,1,5555h
  432.     trans    dx,cx,1,5555h
  433.         ; Store result
  434.     mov    si,sp
  435.     mov    di,ss:[si+20]            ; dist
  436.     lds    si,ss:[si+16]            ; outp
  437.     mov    [si],ah
  438. istore    macro    reg
  439.     add    si,di
  440.     mov    [si],reg
  441.     endm
  442.     istore    bh
  443.     istore    ch
  444.     istore    dh
  445.     istore    al
  446.     istore    bl
  447.     istore    cl
  448.     istore    dl
  449.         ; All done
  450.     pop    di
  451.     pop    si
  452.     pop    ds
  453.     ret
  454. _memflip8x8 ENDP
  455.  
  456.  
  457. utilasm_TEXT ENDS
  458.     END
  459.